# -*- coding: utf-8 -*-            
# @Author : HJH
# @Time : 2024/8/11 14:44
# @Use :
import base64
import gzip
import hashlib
import hmac
import concurrent.futures
import json
import time
import uuid
from functools import lru_cache

import pandas as pd
import requests
from loguru import logger

APP_ID = '76345376'
APP_KEY = 'cgoyl'
APP_SECRET = 'cgoyl@tcjp'


def sign(url: str, body: str, token: str) -> str:
    hash_key = APP_SECRET + token
    message = url + body

    # 将密钥和消息转换为字节
    key_bytes = hash_key.encode('utf-8')
    message_bytes = message.encode('utf-8')

    # 创建一个新的 HMAC 对象，使用 SHA-256 哈希算法
    hmac_obj = hmac.new(key_bytes, message_bytes, hashlib.sha256)

    # 获取 HMAC 值的十六进制表示
    hmac_hex = hmac_obj.hexdigest()

    # 返回小写的十六进制 HMAC 值
    return hmac_hex.lower()


@lru_cache(maxsize=None)
def create_accesstoken():
    body = {
        "app_id": APP_ID,  # 类型：String  必有字段  备注：供应商ID
        "app_key": APP_KEY  # 类型：String  必有字段  备注：供应商账号
    }

    # 获取当前时间的时间戳（秒数）
    timestamp = str(int(time.time()))

    url = f"/openapi/create/accesstoken?t={timestamp}"

    x_tg_token = timestamp
    x_tg_sign = sign(url, json.dumps(body), timestamp)

    response = send_tongc_request(body, url, x_tg_token, x_tg_sign)
    return json.loads(response.text)['access_token']


def refresh_cache():
    create_accesstoken.cache_clear()
    return create_accesstoken()


def parity_oneway_query(params):
    body = {
        "messageBody": {  # 类型：Object  必有字段  备注：请求内容
            "airlineCode": "KN",  # 类型：String  可有字段  备注：航司二字码
            "startPort": params['出发'],  # 类型：String  必有字段  备注：出发机场三字码
            "endPort": params['到达'],  # 类型：String  必有字段  备注：抵达机场三字码
            # "flightNo": params['航班号'],  # 类型：String  可有字段  备注：航班号
            "flyDate": params['出发日期'],  # 类型：String  可有字段  备注：出发日期，格式：yyyy-MM-dd
            # "flyDateRange": {  # 类型：Object  可有字段  备注：出发日期区间 出发日期区间和出发日期 两者必须只能填一个，不能同时填或同时不填
            #     "startDate": params['开始日期'],  # 类型：String  必有字段  备注：无
            #     "endDate": params['结束日期']  # 类型：String  必有字段  备注：无
            # },
            "shareType": 2,  # 类型：Number  可有字段  备注：航班共享类型 0-全部 1-共享 2-非共享 不传默认是0
            "reimbursementType": 2  # 类型：Number  可有字段  备注：报销类型 1-行程单 ,2-发票+行程单 不传默认是2
        },
        "messageHead": {  # 类型：Object  必有字段  备注：请求头部
            "userName": APP_KEY,  # 类型：String  必有字段  备注：接口账号，和app_key一致
            "requestGuid": str(uuid.uuid4())  # 类型：String  必有字段  备注：请求唯一标识
        }
    }

    # 获取当前时间的时间戳（秒数）
    timestamp = str(int(time.time()))

    url = f"/Parity/Oneway/Query?t={timestamp}"

    x_tg_token = create_accesstoken()
    x_tg_sign = sign(url, json.dumps(body), x_tg_token)
    response = send_tongc_request(body, url, x_tg_token, x_tg_sign)

    if response.status_code == 401:
        x_tg_token = refresh_cache()
        x_tg_sign = sign(url, json.dumps(body), x_tg_token)
        response = send_tongc_request(body, url, x_tg_token, x_tg_sign)

    res_data = json.loads(response.text)
    if not res_data['success']:
        return None
    encoded_data = res_data['data']
    # 从 Base64 解码
    decoded_data = base64.b64decode(encoded_data)

    res = gzip.decompress(decoded_data)
    json_data = json.loads(res.decode('utf-8'))
    res_data['data'] = json_data
    return res_data


def award_route_query():
    body = {
        "messageBody": {  # 类型：Object  必有字段  备注：无
        },
        "messageHead": {  # 类型：Object  必有字段  备注：无
            "userName": APP_KEY,  # 类型：String  必有字段  备注：接口账号，和app_key一致
            "requestGuid": str(uuid.uuid4())  # 类型：String  必有字段  备注：请求唯一标识
        }
    }

    # 获取当前时间的时间戳（秒数）
    timestamp = str(int(time.time()))

    url = f"/Award/Route/Query?t={timestamp}"

    x_tg_token = create_accesstoken()
    x_tg_sign = sign(url, json.dumps(body), x_tg_token)
    response = send_tongc_request(body, url, x_tg_token, x_tg_sign)

    if response.status_code == 401:
        x_tg_token = refresh_cache()
        x_tg_sign = sign(url, json.dumps(body), x_tg_token)
        response = send_tongc_request(body, url, x_tg_token, x_tg_sign)

    res_data = json.loads(response.text)
    if not res_data['success']:
        return None
    return res_data


def award_policy_submit(dep, arr, dep_date, flight_no, policy_id):
    body = {
        "messageBody": {  # 类型：Object  必有字段  备注：请求内容
            "startPort": dep,  # 类型：String  必有字段  备注：出发机场三字码
            "endPort": arr,  # 类型：String  必有字段  备注：抵达机场三字码
            "flightNo": flight_no,  # 类型：String  必有字段  备注：航班号
            "flightDate": dep_date,  # 类型：String  必有字段  备注：出发日期，格式：yyyy-MM-dd
            "policyBidRuleId": policy_id  # 类型：String  必有字段  备注：跟投规则guid
        },
        "messageHead": {  # 类型：Object  必有字段  备注：请求头部
            "userName": APP_KEY,  # 类型：String  必有字段  备注：接口账号，和app_key一致
            "requestGuid": str(uuid.uuid4())  # 类型：String  必有字段  备注：请求唯一标识
        }
    }

    # 获取当前时间的时间戳（秒数）
    timestamp = str(int(time.time()))

    url = f"/Award/Policy/Submit?t={timestamp}"

    x_tg_token = create_accesstoken()
    x_tg_sign = sign(url, json.dumps(body), x_tg_token)
    response = send_tongc_request(body, url, x_tg_token, x_tg_sign)

    if response.status_code == 401:
        x_tg_token = refresh_cache()
        x_tg_sign = sign(url, json.dumps(body), x_tg_token)
        response = send_tongc_request(body, url, x_tg_token, x_tg_sign)

    res_data = json.loads(response.text)
    if not res_data['success']:
        logger.error(f"【优势航线推送】【{dep}-->{arr} {dep_date} {flight_no}】{res_data}")
        return None
    logger.info(f"【优势航线推送】【{dep}-->{arr} {dep_date} {flight_no}】{res_data}")
    return res_data


def send_tongc_request(body, url_path, x_tg_token, x_tg_sign):
    url = f"https://flightopenapi.17u.cn{url_path}"
    headers = {
        "x-tg-token": x_tg_token,
        "x-tg-sign": x_tg_sign,
        "x-appkey": APP_KEY,
        "Content-Type": "application/json"
    }

    """
        请求接口
    """
    max_tries = 5  # 最大尝试次数
    num_tries = 0  # 已尝试次数
    sleep_time2 = 3  # 设置等待时间
    while num_tries < max_tries:
        try:
            response = requests.post(url, headers=headers, data=json.dumps(body))
            # logger.info("【同程请求结果】: {}", response.text)
            if response.status_code != 200 and response.status_code != 401:
                logger.error("【同程请求结果】: {}", response.text)
                num_tries += 1
                if num_tries >= max_tries:
                    # 如果已经尝试到最大次数，跳出循环，放弃重试
                    logger.error(f"重试{max_tries}次后仍然失败，放弃重试。")
                    return
                continue
            # 成功请求到数据，直接返回
            return response
        except requests.exceptions.RequestException as e:
            logger.error(e)
            num_tries += 1
            if num_tries >= max_tries:
                # 如果已经尝试到最大次数，跳出循环，放弃重试
                logger.error(f"重试{max_tries}次后仍然失败，放弃重试。")
                return
            # 打印日志，并且睡眠
            logger.warning(f"请求失败，休眠 {sleep_time2} 秒后进行第 {num_tries + 1} 次尝试。")
            time.sleep(sleep_time2)


if __name__ == '__main__':
    # res_data_list = award_route_query()
    #
    # award_policy_submit("TAO", "HRB", "2024-08-24", "MF8071", "b9b36fe29e864a21a1717de648af98a6")

    # # 将列表转换为 DataFrame
    # df = pd.DataFrame(res_data_list['data'])
    #
    # # # 设置表头
    # # header = ['航班号', '出发日期', '']
    #
    # print("开始写入文件... ...")
    # # 将数据写入 Excel 文件并设置表头
    # with pd.ExcelWriter(fr'../docs/奖励航线数据.xlsx', engine='xlsxwriter') as writer:
    #     df.to_excel(writer, index=False, )
    #
    # # 输出成功提示
    # print("Excel 文件写入成功！")
    # flight_info = {
    #     'flight_no': 'CZ6742',
    #     'dep': 'CGQ',
    #     'arr': 'SWA',
    #     'dep_date': '2024-08-12',
    # }
    # res_data = parity_oneway_query(flight_info)
    # print(res_data)

    # # 假设你有一个 gzip 压缩的字节流数据
    # encoded_data = 'H4sIAAAAAAAAA+2Z72vTQBjH/xXJ6y3cXX733dZSndBRW2W4shdZc5sHaVLSRFfKXoyBdjpxIFJ850BkKKIvhsyJ/82y1f/Cu6TdJoa1uC5tYt/l7nl6uef5PN97rm2lxenEMYmFs7aBuQyXXeZmuKq+SqzexFx/XCBW3ig6pMpmoSIAHoDA5jgEO3mTrD9yF21qo5PYMoq249JBeYktsKY7uOSZOLT2Rzns6sTkMpZnmuHs/Wad+UjM6WLB7LKsiCiYa+Z0l3kggMRZoM5CdAtqGYFthDTyZKO3P8CGZa9eN+nWSrgxT4yS7bmhpUas8zBEUeWRQj9dt01SbS4Y4Q7rjm14VbdIrEW9xhz9vd2zgxdnO99Pt99RewOba4VLyyhIDrPBDMU/lgpmen5saHsOexboo6s7bi9N2dv3qPEJscpuECDYnImdTL4EgQgRjCBE97KOS7q1Tv0qKzS5Rkiq0uKsMEEnRy9/vd3z29/opx/rphfEwDwbc2EUBVxbxQ5byuqn9MNlX5p0vdHA9BVO70UtrqZvcBktIMZl4ObmuIpE0cKMDiqS11vdwwP/2XF3f/fvIhlhdQhDVMeD6OrQYCp0K0uQF5OGZPSCLWfhv8m1e/zp5MfP7petCwnC0cgV9OQKxiZXBSJe+d9rYxi5xkekH8UAIt32R//V0Wmn021/9Y8714MCp1CuhqJpPIxVJuD6RMrRRNSb7GqxETmPImEySTcUIMd8+ZseXAOIIHodVxN2cN2JJIIgSMV1XBUBL0nTK9cEiUSlIomVyAhEkmoiGqRExCmRCSLCGomQMCKF6EaC1DQ0EgSoSJRYRTJtJFcTgUjltaSJZD5aJKKSCpEgoPJqrBfgEYhkIRqJcpMX4NiIiPJw39z9N0/95/v++8OzzztjJ/IwmogspUIkMlR4CSZMJEtjQBIfEVHl5WH+a52kTpLqY+s8ioT94JiLhCLQxpgCKJqawF6SjSYipaKXCIIkJA/J3UgkkpCGk0tCMuKDpSeHyMpvG5s+UUwlAAA='
    # # 从 Base64 解码
    # decoded_data = base64.b64decode(encoded_data)
    #
    # res = gzip.decompress(decoded_data)
    # json_data = json.loads(res.decode('utf-8'))
    #
    # # 打印解压缩后的数据（假设数据是文本）
    # print(json_data)
    #
    # # 将列表转换为 DataFrame
    # df = pd.DataFrame(json_data)
    #
    # # # 设置表头
    # # header = ['航班号', '出发日期', '']
    #
    # print("开始写入文件... ...")
    # # 将数据写入 Excel 文件并设置表头
    # with pd.ExcelWriter(fr'../docs/同程比价记录.xlsx', engine='xlsxwriter') as writer:
    #     df.to_excel(writer, index=False, )
    #
    # # 输出成功提示
    # print("Excel 文件写入成功！")
    pass
